﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Go;
using GoRpc;

namespace GoRpcTest
{
    class Program
    {
        class remote_obj
        {
            int value1 = 0;
            int value2 = 0;

            async Task<int> add()
            {
                await generator.sleep(1000);
                return value1 + value2;
            }

            async Task<int> sub()
            {
                await generator.sleep(1000);
                return value1 - value2;
            }
        }

        static void Main(string[] args)
        {
            work_service work = new work_service();
            work_strand strand = new work_strand(work);
            generator.go(strand, async delegate ()
            {
                Rpc.Methods methods = new Rpc.Methods();
                methods.BindObj("remote", new remote_obj());
                socket_tcp.acceptor accep = new socket_tcp.acceptor();
                if (!accep.bind("127.0.0.1", 2001))
                {
                    return;
                }
                socket_tcp socket = new socket_tcp();
                if (!await accep.accept(socket))
                {
                    return;
                }
                accep.close();
                generator.children sessions = new generator.children();
                Rpc.Session sess = new Rpc.Session(socket, methods);
                sessions.go(async delegate ()
                {
                    await sess.Run();
                    Console.WriteLine("Server.Disconnected");
                });
                sessions.go(async delegate ()
                {
                    await sess.Call("remote.set@value1", 123);
                    await sess.Call("remote.set@value2", 456);
                    Rpc.Result<int> r1 = await sess.Call<int>("remote.add");
                    Rpc.Result<int> r2 = await sess.Call<int>("remote.sub");
                    Console.WriteLine($"Server.Add {r1.result}");
                    Console.WriteLine($"Server.Sub {r2.result}");
                });
                await sessions.wait_all();
            });
            generator.go(strand, async delegate ()
            {
                await generator.sleep(100);
                Rpc.Methods methods = new Rpc.Methods();
                methods.BindObj("remote", new remote_obj());
                socket_tcp socket = new socket_tcp();
                if (await socket.connect("127.0.0.1", 2001))
                {
                    generator.children sessions = new generator.children();
                    Rpc.Session sess = new Rpc.Session(socket, methods);
                    sessions.go(async delegate ()
                    {
                        await sess.Run();
                        Console.WriteLine("Client.Disconnected");
                    });
                    await sess.Call("remote.set@value1", 456);
                    await sess.Call("remote.set@value2", 123);
                    Rpc.Result<int> r1 = await sess.Call<int>("remote.add");
                    Rpc.Result<int> r2 = await sess.Call<int>("remote.sub");
                    Console.WriteLine($"Client.Add {r1.result}");
                    Console.WriteLine($"Client.Sub {r2.result}");
                    sess.Close();
                    await sessions.wait_all();
                }
                socket.close();
            });
            work.run();
            Console.WriteLine("work done");
            Console.ReadKey();
        }
    }
}
